package mock.bo;

import java.util.List;

import mock.dao.AccountDAO;
import mock.dao.AccountDAOImp;
import mock.dao.CardDAO;
import mock.dao.CardDAOImp;
import mock.dao.ConfigDAO;
import mock.dao.ConfigDAOImp;
import mock.dao.LogDAO;
import mock.dao.LogDAOImp;
import mock.dao.MoneyDAO;
import mock.dao.MoneyDAOImp;
import mock.dao.OverDraftDAO;
import mock.dao.OverDraftDAOImp;
import mock.dao.StockDAO;
import mock.dao.StockDAOImp;
import mock.dao.WithdrawLimitDAO;
import mock.dao.WithdrawLimitDAOImp;
import mock.dto.AccountDTO;
import mock.dto.CardDTO;
import mock.dto.ConfigDTO;
import mock.dto.LogDTO;
import mock.dto.StockDTO;
import mock.utility.Utility;

public class WithdrawImp implements Withdraw{
	
	private Utility util = new Utility();
	private StockDAO stockDAO = new StockDAOImp();
	private MoneyDAO moneyDAO = new MoneyDAOImp();
	private LogDAO logDAO = new LogDAOImp();
	private WithdrawLimitDAO wdlimitDAO = new WithdrawLimitDAOImp();
	private CardDAO cardDAO = new CardDAOImp();
	private AccountDAO accountDAO = new AccountDAOImp();
	private ConfigDAO configDAO = new ConfigDAOImp();
	private OverDraftDAO overDraftDAO = new OverDraftDAOImp();
	
	private ConfigDTO config = configDAO.getLastConfig();
	
	/**
	 * tra ve so tien trong may ATM
	 * @param atmID
	 * @return
	 */
	private double getAllMoneyInStock(int atmID){ 
		double stockSum = 0;
		List<StockDTO> stockList = stockDAO.getStockByATMID(atmID);
		if(stockList != null){
			for(StockDTO stock : stockList){
				double moneyValue = moneyDAO.getMoneyValueByID(stock.getMoneyID());
				stockSum += stock.getQuantity() * moneyValue;
			}
			return stockSum;
		}else{
			return -1;
		}
	}
	
	/**
	 * lay so tien user da rut trong ngay hien tai
	 * @param cardNo
	 * @return
	 */
	private double getAllMoneyWithdrawInLog(String cardNo){
		double logSum = 0;
		List<LogDTO> logList = logDAO.getLogByCardNoAndDateAndLogTypeID(cardNo, util.getCurrentDate(), 1);
		if(logList != null){
			for(LogDTO log : logList){
				logSum += log.getAmount();
			}
			return logSum;
		}else{
			return -1;
		}
	}
	
	/**
	 * input: cardNo, atmID, amount
	 * output: withdraw success or not
	 */
	@Override
	public boolean withdraw(String cardNo, int atmID, double amount) {
		// TODO Auto-generated method stub
		//check stock
		double stockMoney = getAllMoneyInStock(atmID);
		if(amount > stockMoney) return false; 
		//check limit each day
		double withdrawMoneyInDay = getAllMoneyWithdrawInLog(cardNo);
		CardDTO card = cardDAO.getCardByCardNo(cardNo);
		AccountDTO account = null;
		if(card != null) account = accountDAO.getAccountByAccountID(card.getAccountID());
		else return false;
		double withdrawLimit = -1;
		if(account != null) withdrawLimit = wdlimitDAO.getWithdrawLimitByWDID(account.getWdid());
		else return false;
		if(withdrawLimit != -1){
			if((amount + withdrawMoneyInDay) > withdrawLimit) return false;
		}
		//check limit each time
		//check min each time
		if(config != null){
			double max = config.getMaxWithdraw();
			double min = config.getMinWithdraw();
			if(max != -1){
				if(amount > max) return false;
			}
			if(min != -1){
				if(amount < min) return false;
			}
		}
		//check balance
		double balance = account.getBalance();
		double overdraft = overDraftDAO.getOverDraftByODID(account.getOdid());
		if(balance != -1){
			if(amount > balance){
				if(overdraft != -1){
					if(amount > (balance + overdraft)) return false;
				}else return false;
			}
		}else return false;
		//withdraw
			double newBalance = account.getBalance() - amount;
			boolean chk = accountDAO.updateNewBalanceByAccountID(account.getAccountID(), newBalance);
			int[] quantity = new int[4];
			int[] standardValue = {500000, 200000, 100000, 50000};
			int temp = (int)amount;
			int i = 0;
			do{
				quantity[i] = temp / standardValue[i];
				temp = temp % standardValue[i];
				i++;
			}while(i < 4);
			for(int j = 0; j < quantity.length; j++){
				StockDTO stock = stockDAO.getStockByATMIDAndMoneyID(atmID, (j + 1));
				int originalQuantity = stock.getQuantity();
				int newQuantity = originalQuantity - quantity[j];
				stockDAO.updateStockByATMIDAndQuantityAndMoneyID(atmID, (j+1), newQuantity);
			}
			if(chk == true) return true;
			else return false;
	}

}
